﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Collections;
using SKYPE4COMLib;
using System.Timers;

namespace SoundServant
{
    public class Listener
    {
        string name;
        bool participateByDefault;
        public readonly int Id;
        string contact;
        bool inCall = false;
        ListenerState state = ListenerState.Disconnected;

        DateTime timeCallStartedAt;
        TimeSpan finishedCallDuration;
        Congregation congregation;

        Call callHandle;
        TCallStatus callStatus = TCallStatus.clsUnknown;

        public Call CallHandle { get { return callHandle; } }
        public TCallStatus CallStatus { get { return callStatus; } }
        public int CallId { get { return callHandle.Id; } }
        public TimeSpan CallDuration
        {
            get
            {
                if (state == ListenerState.InCall)
                {
                    return new TimeSpan(0, 0, callHandle.Duration);
                }
                else if (callStatus == TCallStatus.clsFinished)
                    return finishedCallDuration;
                else
                    return new TimeSpan(0, 0, 0);
            }
        }

        public string Name { get { return name; } set { name = value; Update(); } }
        public bool ParticipateByDefault { get { return participateByDefault; } set { participateByDefault = value; Update(); } }
        public string Contact { get { return contact; } set { contact = value; Update(); } }
        public ListenerState State { get { return state; } }


        public delegate void VoidEventHandler();
        public event VoidEventHandler Updated;
        public event VoidEventHandler CallStatusUpdated;
        public event VoidEventHandler CallStarted;
        public event VoidEventHandler CallFinished;
        public delegate bool ListenerEventHandler(Listener listener);
        public event ListenerEventHandler ConnectRequest;

        private void Update()
        {
            SqlConnection connection = SS.Connection();
            SqlCommand dbCommand = new SqlCommand("UPDATE listeners SET listenerName = '" + name + "', listenerEnabled = '" + participateByDefault.ToString() + "', listenerContact = '" + contact + "' WHERE listenerId = " + Id, connection);
            dbCommand.ExecuteNonQuery();
            if (Updated != null) Updated();
            connection.Close();
            connection.Dispose();
            if (Updated != null) Updated();
        }

        public void Delete()
        {
            SqlConnection connection = SS.Connection();
            SqlCommand dbCommand = new SqlCommand("DELETE FROM listeners WHERE listenerId = " + Id, connection);
            dbCommand.ExecuteNonQuery();
            connection.Close();
        }

        public void Toggle()
        {
            if (state == ListenerState.InCall || state == ListenerState.Calling)
            {
                Disconnect();
            }
            else if (state == ListenerState.Disconnected)
            {
                if (ConnectRequest(this))
                    state = ListenerState.Ready;
            }
            else if (state == ListenerState.Ready)
            {
                state = ListenerState.Disconnected;
            }

            CallStatusUpdated();
        }

        public void Connect()
        {
            if (ConnectRequest != null) ConnectRequest(this);
        }

        public void Disconnect()
        {
            if (state == ListenerState.InCall || state == ListenerState.Calling)
            {
                try
                {
                    Logs.Information("Skype", "Disconnecting listener - Name: " + name + " Handle: " + contact + " Call Id: " + callHandle.Id + " Conference Id: " + callHandle.ConferenceId);
                    callHandle.Finish();
                }
                catch (Exception)
                {
                }
            }
        }

        public void UpdateCallStatus(Call newCallHandle, TCallStatus newCallStatus)
        {
            callHandle = newCallHandle;

            if (state != ListenerState.Disconnected && Sharing.HasCallFinished(newCallStatus))
            {
                    finishedCallDuration = new TimeSpan(0, 0, newCallHandle.Duration);
                    state = ListenerState.Disconnected;
                    if (CallFinished != null) CallFinished();
            }
            else if (state != ListenerState.InCall && Sharing.IsCallInProgress(newCallStatus))
            {
                    state = ListenerState.InCall;
                    if (CallStarted != null) CallStarted();
            }
            else if (state != ListenerState.Disconnected && Sharing.HasCallFailed(newCallStatus))
            {
                    finishedCallDuration = new TimeSpan(0, 0, 0);
                    state = ListenerState.Disconnected;
                    if (CallFinished != null) CallFinished();
            }
            else if (Sharing.IsCallRinging(newCallStatus))
            {
                state = ListenerState.Calling;
            }
            else if (Sharing.IsAnswerMachine(newCallStatus))
            {
                Disconnect();
                if (CallFinished != null) CallFinished();
            }

            callStatus = newCallStatus;
            CallStatusUpdated();
        }

        public Listener(int _id)
        {
            Id = _id;

            SqlCommand dbCommand;
            SqlDataReader dbReader;
            SqlConnection connection = SS.Connection();

            dbCommand = new SqlCommand("SELECT * FROM listeners WHERE listenerId = " + Id, connection);
            dbReader = dbCommand.ExecuteReader();
            dbReader.Read();

            name = dbReader["listenerName"].ToString();
            contact = dbReader["listenerContact"].ToString();
            participateByDefault = (bool)dbReader["listenerEnabled"];
            if (participateByDefault) state = ListenerState.Ready;

            dbReader.Close();
            connection.Close();
        }

        public Listener(string _name, string _contact, bool _participateByDefault, Congregation _congregation)
        {
            congregation = _congregation;

            SqlConnection connection = SS.Connection();
            SqlCommand dbCommand = new SqlCommand("INSERT INTO listeners (listenerName, listenerContact, listenerEnabled, listenerType, listenerCong) VALUES ('" + _name + "', '" + _contact + "', '" + _participateByDefault.ToString() + "', 0, " + congregation.Id + ") SELECT CAST(scope_identity() AS int)", connection);
            Id = (int)dbCommand.ExecuteScalar();
            connection.Close();
            connection.Dispose();

            name = _name;
            contact = _contact;
            participateByDefault = _participateByDefault;
            if (participateByDefault) state = ListenerState.Ready;
        }

        public static ArrayList GetAllListeners(Congregation _cong)
        {
            SqlCommand dbCommand;
            SqlDataReader dbReader;
            SqlConnection connection = SS.Connection();
            dbCommand = new SqlCommand("SELECT listenerId FROM listeners WHERE listenerCong = " + _cong.Id, connection);
            dbReader = dbCommand.ExecuteReader();

            ArrayList listeners = new ArrayList();

            if (dbReader.HasRows)
            {
                while (dbReader.Read())
                {
                    listeners.Add(new Listener(int.Parse(dbReader[0].ToString())));
                }
            }

            dbReader.Close();
            connection.Close();

            return listeners;
        }
    }

    public enum ListenerType
    {
        Telephone,
        Skype
    }
    public enum ListenerState
    {
        Ready,
        InCall,
        Disconnected,
        Calling
    }
}

